package com.cold.legendary.bprocess.trigger.impl;

import com.alibaba.fastjson.JSON;
import com.cold.legendary.bprocess.common.constance.BErrorCodeEnum;
import com.cold.legendary.bprocess.common.exception.BProcessException;
import com.cold.legendary.bprocess.common.exception.BProcessInterruptException;
import com.cold.legendary.bprocess.context.enums.CallWayEnum;
import com.cold.legendary.bprocess.context.ins.BArrowIns;
import com.cold.legendary.bprocess.context.ins.BPointIns;
import com.cold.legendary.bprocess.context.run.BContext;
import com.cold.legendary.bprocess.db.enums.PointRunStatusEnum;
import com.cold.legendary.bprocess.db.model.TbProcessRequest;
import com.cold.legendary.bprocess.definition.point.BPointService;
import com.cold.legendary.bprocess.trigger.AbstractBProcessTriggerService;
import com.cold.legendary.bprocess.trigger.BProcessTriggerService;
import com.cold.legendary.bprocess.trigger.enums.TriggerModeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

/**
 * @author cold
 * @since 2023/3/10
 */
@Slf4j
@Service
public class RetryBProcessTriggerService extends AbstractBProcessTriggerService {

    @Override
    public void triggerBPoint(BPointIns triggerBPointIns, BContext bContext) {
        try {
            //校验流程请求
            TbProcessRequest qryProcessRequest = processRequestCheckHelper.checkProcessRequest(bContext);
            //基础业务校验
            baseCheck(bContext, triggerBPointIns, qryProcessRequest);

            if (!PointRunStatusEnum.ERROR.getCode().equals(qryProcessRequest.getPointRunStatus())) {
                log.error("此节点非错误状态!无法触发retry!bizId={}, merchantId={},processId={}",
                        bContext.getBizId(), bContext.getMerchantId(), bContext.getProcessId());
                throw new BProcessException(BErrorCodeEnum.SYS_ONLY_ERROR_POINT_ERROR);
            }

            //执行当前节点重试业务逻辑
            log.info("<retry>-开始...triggerBPointId={}, bContext={}", triggerBPointIns.getPointId(), JSON.toJSONString(bContext));
            BPointService bPointService = triggerBPointIns.getBPointService();
            bPointService.execute(bContext);
            log.info("<retry>-结束...triggerBPointId={}, bContext={}", triggerBPointIns.getPointId(), JSON.toJSONString(bContext));

            //重试成功后,变更状态到processing
            bProcessTransactionService.processingErrorPoint(bContext);

            //判断当前节点是正常节点还是等待节点
            if (CallWayEnum.NORMAL == triggerBPointIns.getCallWayEnum()) {
                BArrowIns nextBArrowIns = triggerBPointIns.getNextBArrowIns();
                BPointIns nextBPointIns = nextBArrowIns.getNextBPointIns();
                //调用执行
                BProcessTriggerService triggerService = factory.getBProcessTriggerService(TriggerModeEnum.EXECUTE);
                triggerService.triggerBPoint(nextBPointIns, bContext);
            } else if (CallWayEnum.WAIT == triggerBPointIns.getCallWayEnum()) {
                //修改节点状态为等待中
                bProcessTransactionService.waitPoint(bContext, triggerBPointIns.getPointId());
            }
        } catch (BProcessInterruptException e) {
            log.info("捕捉到节点中断信号!执行中断逻辑! code={}, msg={}", e.getCode(), e.getMsg());
            if(StringUtils.isEmpty(bContext.getFailReason())) {
                bContext.setFailReason(e.getMsg());
            }
            bProcessService.interruptBProcess(bContext);
        } catch (Exception e) {
            log.error("重试节点逻辑发生异常!", e);
            bProcessTransactionService.errorPoint(bContext, e);
        }
    }


    @Override
    protected TriggerModeEnum getTriggerModeEnum() {
        return TriggerModeEnum.RETRY;
    }
}
